---
displayed_sidebar: "Chinese"
---

# 更新表

建表时，支持定义主键和指标列，查询时返回主键相同的一组数据中的最新数据。相对于明细表，更新表简化了数据导入流程，能够更好地支撑实时和频繁更新的场景。

## 适用场景

实时和频繁更新的业务场景，例如分析电商订单。在电商场景中，订单的状态经常会发生变化，每天的订单更新量可突破上亿。

## 原理

更新表可以视为聚合表的特殊情况，指标列指定的聚合函数为 REPLACE，返回具有相同主键的一组数据中的最新数据。

数据分批次多次导入至更新表，每一批次数据分配一个版本号，因此同一主键的数据可能有多个版本，查询时返回版本最新（即版本号最大）的数据。相对于明细表，更新表通过简化导入流程，能够更好地支持实时和频繁更新。

例如下表中，`ID` 是主键，`value` 是指标列，`_version` 是 StarRocks 内部的版本号。其中，`ID` 为 1 的数据有两个导入批次，版本号分别为 `1` 和 `2`；`ID` 为 `2` 的数据有三个导入批次，版本号分别为 `3`、`4`、`5`。

| ID   | value | _version |
| ---- | ----- | -------- |
| 1    | 100   | 1        |
| 1    | 101   | 2        |
| 2    | 100   | 3        |
| 2    | 101   | 4        |
| 2    | 102   | 5        |

查询 `ID` 为 `1` 的数据时，仅会返回最新版本 `2` 的数据，而查询 `ID` 为 `2` 的数据时，仅会返回最新版本 `5` 的数据，最终查询结果如下：

| ID   | value |
| ---- | ----- |
| 1    | 101   |
| 2    | 102   |

## 创建表

在电商订单分析场景中，经常按照日期对订单状态进行统计分析，则可以将经常使用的过滤字段订单创建时间 `create_time`、订单编号 `order_id` 作为主键，其余列订单状态 `order_state` 和订单总价 `total_price` 作为指标列。这样既能够满足实时更新订单状态的需求，又能够在查询中进行快速过滤。

在该业务场景下，建表语句如下：

```SQL
CREATE TABLE IF NOT EXISTS orders (
    create_time DATE NOT NULL COMMENT "create time of an order",
    order_id BIGINT NOT NULL COMMENT "id of an order",
    order_state INT COMMENT "state of an order",
    total_price BIGINT COMMENT "price of an order"
)
UNIQUE KEY(create_time, order_id)
DISTRIBUTED BY HASH(order_id)
PROPERTIES (
"replication_num" = "3"
); 
```

> **注意**
>
> - 建表时必须使用 `DISTRIBUTED BY HASH` 子句指定分桶键。分桶键的更多说明，请参见[分桶](../Data_distribution.md#分桶)。
> - 自 2.5.7 版本起，StarRocks 支持在建表和新增分区时自动设置分桶数量 (BUCKETS)，您无需手动设置分桶数量。更多信息，请参见 [设置分桶数量](../Data_distribution.md#设置分桶数量)。

## 使用说明

- 主键的相关说明：
  - 在建表语句中，主键必须定义在其他列之前。
  - 主键通过 `UNIQUE KEY` 定义。
  - 主键必须满足唯一性约束，且列的值不会修改。
  - 设置合理的主键。
    - 查询时，主键在聚合之前就能进行过滤，而指标列的过滤通常在多版本聚合之后，因此建议将频繁使用的过滤字段作为主键，在聚合前就能过滤数据，从而提升查询性能。
    - 聚合过程中会比较所有主键，因此需要避免设置过多的主键，以免降低查询性能。如果某个列只是偶尔会作为查询中的过滤条件，则不建议放在主键中。

- 建表时，不支持为指标列创建 BITMAP、Bloom Filter 等索引。

## 下一步

建表完成后，您可以创建多种导入作业，导入数据至表中。具体导入方式，请参见[导入概览](../../loading/Loading_intro.md)。

> - 导入数据时，仅支持全部更新，即导入任务需要指明所有列，例如示例中的 `create_time`、`order_id`、`order_state` 和 `total_price` 四个列。
>
> - 在设计导入频率时，建议以满足业务对实时性的要求为准。查询更新表的数据时，需要聚合多版本的数据，当版本过多时会导致查询性能降低。所以导入数据至更新表时，应该适当降低导入频率，从而提升查询性能。如果业务对实时性的要求是分钟级别，那么每分钟导入一次更新数据即可，不需要秒级导入。
